import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;


public class Servers {
	private static Environment _env = new Environment();
	
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		AutoHelpParser helpParser = new AutoHelpParser();
		// init option 
		CmdLineParser.Option<Integer> protocol =
				helpParser.addHelp(
							helpParser.addIntegerOption('p', "protocol"), 
							"Choose 0 for TCP or 1 for UDP.Default is 0");
		CmdLineParser.Option<String> size =
				helpParser.addHelp(
							helpParser.addStringOption('s', "size"), 
							"Block Size of the the package's buffer: B, KB or KB64. Default is B.");
		CmdLineParser.Option<Integer> thread =
				helpParser.addHelp(
							helpParser.addIntegerOption('t', "thread"), 
							"Number of thread. Default is 1. Max is 2.");
		
		// init help
		CmdLineParser.Option<Boolean> help = 
				helpParser.addHelp(helpParser.addBooleanOption('h',"help"), "Print this page");

		try {
			helpParser.parse(args);
		} catch (CmdLineParser.OptionException e) {
			helpParser.printUsage();
			e.printStackTrace();
		}

		if (helpParser.getOptionValue(help) != null){
			helpParser.printUsage();
			System.exit(0);
		}

		_env.generatePort();
		
		Integer protocolValue = helpParser.getOptionValue(protocol);
		String sizeValue = helpParser.getOptionValue(size);
		Integer threadValue = helpParser.getOptionValue(thread);
		if(sizeValue == null || sizeValue.equals("B")){
			_env.set_size(Environment.B);
		}else if (sizeValue.equals("KB")){
			_env.set_size(Environment.KB); 
		}else if (sizeValue.equals("KB64")){
			_env.set_size(Environment.KB64); 
		}
		if(threadValue != null){
			_env.set_nbThread(threadValue);			
		}
		
		
		if(protocolValue == null || protocolValue == 0){
			try {
				runServerTCP();
			} catch (Exception e) {
				e.printStackTrace();
			}
		}else {
			try {
				runServerUDP();
			} catch (Exception e) {
				e.printStackTrace();
			}
		}

	}

	
	private static void runServerTCP() throws Exception
	{
		List<ThreadTCP> listTCP = new ArrayList<ThreadTCP>();
		ServerSocket serverSocket = new ServerSocket(_env.get_port());
		Socket connectionSocket;
		
		for (int i =0; i< _env.get_nbThread(); i++){
			connectionSocket = serverSocket.accept();
			
			ThreadTCP tcp = new ThreadTCP(_env, connectionSocket);
			listTCP.add(tcp);
			listTCP.get(i).start();
		}
		for (int i=0; i<_env.get_nbThread(); i++){
			listTCP.get(i).join();
		}
	}
	
	private static void runServerUDP() throws Exception
	{
		List<ThreadUDP> listUDP = new ArrayList<ThreadUDP>();
		int nbThread = _env.get_nbThread(); 
		for(int i=0; i<1; i++){
			ThreadUDP tUDP = new ThreadUDP(_env);
			listUDP.add(tUDP);
			listUDP.get(i).start();
		}
		for(int i=0; i<1; i++){
			listUDP.get(i).join();
		}
	}		

}
